/*
 * Copyright (c) 2018-2024 北京华恒盛世科技有限公司
 * QUICKPOOL is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <string.h>

#include "common.h"

#define SIGEMT  SIGBUS
#define NUM_SIG 32
char const *sigSymbol[NUM_SIG] = {     "",
                                "HUP",
                                "INT",
                                "QUIT",
                                "ILL",
                                "TRAP",
                                "ABRT",
                                "BUS",
                                "FPE",
                                "KILL",
                                "USR1",
                                "SEGV",
                                "USR2",
                                "PIPE",
                                "ALRM",
                                "TERM",
                                "STKFLT",
                                "CHLD",
                                "CONT",
                                "STOP",
                                "TSTP",
                                "TTIN",
                                "TTOU",
                                "URG",
                                "XCPU",
                                "XFSZ",
                                "VTALRM",
                                "PROF",
                                "WINCH",
                                "IO",
                                "PWR",
                                "SYS"
};

int
gf_string_2signal(const char *sigString)
{
    int sigVal, i;
    char sigSig[16+1];

    if (sigString == NULL || sigString[0] == '\0')
        return -1;

    if (isinteger(sigString) == TRUE) {
        if ((sigVal=atoi(sigString)) > NUM_SIG)
            return -1;
        else
            return (sigVal);
    }

    for (i=0; i<NUM_SIG; i++) {

        snprintf(sigSig, 16, "%s%s", "SIG", sigSymbol[i]);
        if ((strcmp(sigSymbol[i], sigString) == 0)
            || (strcmp(sigSig, sigString) == 0))
            return (i);
    }

    return -1;
}

char *
sigsymbol_2string(void)
{
    static char list[512];
    int i;

    list[0] = '\0';
    for (i=1; i<NUM_SIG; i++) {
        strcat(list, sigSymbol[i]);
        strcat(list, " ");
    }

    return(list);
}

SIGFUNCTYPE Signal_(int sig, void (*handler)(int))
{
    struct sigaction act, oact;

    act.sa_handler = handler;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask, sig);
    if(sigaction(sig, &act, &oact) == -1){
        oact.sa_handler = (void (*)(int))SIG_ERR;
    }
    return(oact.sa_handler);
}

char *
gf_signal_2string(int sig)
{
    static char symbol[30];

    symbol[0] = '\0';
    if (sig < 0 || sig >= _NSIG) {
        strcpy(symbol, "UNKNOWN");
    } else {
        strcpy(symbol, sigSymbol[sig]);
    }

    return (symbol);
}

int
gf_block_allsignals(sigset_t *newmask, sigset_t *oldmask)
{
    sigfillset(newmask);
    sigdelset(newmask, SIGTRAP);
    sigdelset(newmask, SIGEMT);
    return (sigprocmask(SIG_BLOCK, newmask, oldmask));
}

int
gf_block_signals(int sig, sigset_t *blockmask, sigset_t *oldmask)
{
    sigfillset(blockmask);

    if (sig) {
	sigdelset(blockmask, sig);
    }

    sigdelset(blockmask, SIGHUP);
    sigdelset(blockmask, SIGINT);
    sigdelset(blockmask, SIGQUIT);
    sigdelset(blockmask, SIGILL);
    sigdelset(blockmask, SIGTRAP);
    sigdelset(blockmask, SIGFPE);
    sigdelset(blockmask, SIGBUS);
    sigdelset(blockmask, SIGSEGV);
    sigdelset(blockmask, SIGPIPE);
    sigdelset(blockmask, SIGTERM);

    return (sigprocmask(SIG_BLOCK, blockmask, oldmask));
}

void
gf_unblock_signals(sigset_t *mask)
{
    sigprocmask(SIG_SETMASK, mask, NULL);

    return;
}

